//*****************************************************************************
//
// uart_handler.c - This file contains the function used to transfer data via
//                  a Stellaris UART port.
//
// Copyright (c) 2006-2007 Luminary Micro, Inc.  All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  Any use in violation
// of the foregoing restrictions may subject the user to criminal sanctions
// under applicable laws, as well as to civil liability for the breach of the
// terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 323 of the Stellaris boot loader.
//
//*****************************************************************************

#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "gpio.h"
#include "hw_ssi.h"
#include "hw_uart.h"
#include "hw_nvic.h"
#include "hw_gpio.h"
#include "hw_sysctl.h"
#include "hw_flash.h"

#include "boot_loader.h"

//*****************************************************************************
//
//! \addtogroup uart_handler_src UART Handler APIs
//! This section describes the functions that are responsible for handling the
//! transfer of data over the UART port.
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
//! Sends data over a UART port.
//!
//! \param pucBuffer is the buffer containing the data to write out to the UART
//!     port.
//! \param ucSize is the number of bytes provided in pucData buffer that will
//!     be written out to the UART port.
//!
//! This function sends ucSize bytes of data from the buffer pointed to by
//! pucData via the UART port.
//!
//! \return This function returns zero to indicate success while any non-zero
//! value indicates a failure.
//
//*****************************************************************************
int
UARTSend(unsigned char const *pucBuffer, unsigned char ucSize)
{
    int iOffset;

    //
    // Transmit the number of bytes requested on the UART port.
    //
    for(iOffset = 0; iOffset < ucSize; iOffset++)
    {
        //
        // Make sure that the transmit FIFO is not full.
        //
        while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_TXFF))
        {
        }

        //
        // Send out the next byte.
        //
        HWREG(UART0_BASE + UART_O_DR) = pucBuffer[iOffset];
    }

    //
    // Wait for the UART FIFO to empty and then wait for the shifter to get
    // the bytes out the port.
    //
    while(!(HWREG(UART0_BASE + UART_O_FR) & UART_FR_TXFE))
    {
    }

    //
    // Wait for the FIFO to not be busy so that the shifter completes.
    //
    while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_BUSY))
    {
    }

    //
    // All bytes have been sent out successfully.
    //
    return(0);
}

//*****************************************************************************
//
//! Receives data over a UART port.
//!
//! \param pucBuffer is the buffer to read data into from the UART port.
//! \param ucSize is the number of bytes provided in the pucData buffer that
//!     should be written with data from the UART port.
//!
//! This function reads back ucSize bytes of data from the UART port, into the
//! buffer that is pointed to by pucData.  This function will not return until
//! ucSize number of bytes have been received.
//!
//! \return This function returns zero to indicate success while any non-zero
//!     value indicates a failure.
//
//*****************************************************************************
int
UARTReceive(unsigned char *pucBuffer, unsigned char ucSize)
{
    int iOffset;

    //
    // Send out the number of bytes requested.
    //
    for(iOffset = 0; iOffset < ucSize; iOffset++)
    {
        //
        // Wait for the FIFO to not be empty.
        //
        while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE))
        {
        }

        //
        // Receive a byte from the UART.
        //
        pucBuffer[iOffset] = HWREG(UART0_BASE + UART_O_DR);
    }

    //
    // All bytes requested were received successfully.
    //
    return(0);
}

//*****************************************************************************
//
//! Sets up the serial port.
//!
//! \param iProcRatio is a fixed-point representation of the ratio of the
//!     processor to UART port data rate.  This value is broken down in two
//!     parts, a fractional portion and an integer portion.  The lower 6 bits
//!     are the fractional divisor represented as fract_value/(2^6).  Bits 21
//!     through 6 are the integer portion of the divisor.
//!
//! This function configures the UART port for 8 data bits, no parity, one stop
//! bit, and sets the baud rate based on the iProcRatio.  The iProcRatio can be
//! easily set by using the UART_BAUD_RATIO() macro provided in lmibootlib.h or
//! if auto-baud feature is used, the AutoBaud() function returns a value that
//! can be passed in as the iProcRatio parameter.
//!
//! \return None.
//
//*****************************************************************************
void
UARTConfig(int iProcRatio)
{
    //
    // Enable the UART peripheral.
    //
    HWREG(SYSCTL_RCGC1) = SYSCTL_SET1_UART0;

    //
    // Set the pad(s) for standard push-pull operation.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_PUR) |= UART_RX;
    HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= UART_RX;

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_AFSEL) = (UART_RX | UART_TX);

    //
    // Set the pad(s) for standard push-pull operation.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_DR2R) = (UART_RX | UART_TX);

    //
    // Set the pin type.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) = (UART_RX | UART_TX);

    //
    // Set the baud rate.
    //
    HWREG(UART0_BASE + UART_O_IBRD) = iProcRatio >> 6;
    HWREG(UART0_BASE + UART_O_FBRD) = iProcRatio & UART_FBRD_DIVFRAC_MASK;

    //
    // Set data length, parity, and number of stop bits.
    // 8,N,1
    //
    HWREG(UART0_BASE + UART_O_LCR_H) = UART_LCR_H_WLEN_8;

    //
    // Start the UART.
    //
    HWREG(UART0_BASE + UART_O_LCR_H) |= UART_LCR_H_FEN;

    //
    // Enable RX, TX, and the UART.
    //
    HWREG(UART0_BASE + UART_O_CTL) |= (UART_CTL_UARTEN | UART_CTL_TXE |
                                       UART_CTL_RXE);
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
